package com.fecean.aabbc.commons.easy;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Optional;

/**
 ** 通用数字操作类
 *
 * @author: <a href="mailto:chenfenghai@oristartech.com">chenfenghai</a>
 * @version: 1.0
 * @date: 2019-10-21 14:18
 */
public class EasyNumber {

    /**
     ** The number of BigDecimal
     */
    private BigDecimal bigDecimal;

    // Constructors

    /**
     ** 私有的无参数构造方法
     */
    public EasyNumber(){
        this.bigDecimal = BigDecimal.ZERO;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 私有的带参数构造方法
     *
     * @param bigDecimal 传入数字值
     */
    private EasyNumber(BigDecimal bigDecimal){
        this.bigDecimal = bigDecimal;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 初始化{@code Number}实例，如果传入不是数字格式，则默认为0
     *
     * @param number 传入数字值
     * @return {@code Number}, not null
     */
    public static EasyNumber of(final Object number){
        return new EasyNumber(EasyConverter.of(number).toBigDecimal());
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 初始化Number实例
     *
     * @param number 传入数字值
     * @param defaultNumber 当转换出错时默认数字值
     * @return {@code Number}, not null
     */
    public static EasyNumber of(final Object number, final Object defaultNumber){
        try{
            return of(number);
        }catch (Exception ex){
            return of(defaultNumber);
        }
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     * 加上一个数值
     *
     * @param  augend value to be added to this {@code Number}.
     * @return {@code Number}, not null
     */
    public EasyNumber add(final Object augend) {
        return addDefault(augend, 0);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     * 加上一个数值
     *
     * @param  augend value to be added to this {@code Number}.
     * @return {@code Number}, not null
     */
    public EasyNumber addDefault(final Object augend, final Object defaultNumber) {
        bigDecimal = bigDecimal.add(EasyConverter.of(augend).toBigDecimalDefault(defaultNumber));
        return this;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 减去一个数值
     *
     * @param  subtrahend value to be subtracted from this {@code Number}.
     * @return {@code Number}, not null
     */
    public EasyNumber subtract(final Object subtrahend) {
        return subtractDefault(subtrahend, 0);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 减去一个数值
     *
     * @param  subtrahend value to be subtracted from this {@code Number}.
     * @return {@code Number}, not null
     */
    public EasyNumber subtractDefault(final Object subtrahend, final Object defaultNumber) {
        bigDecimal = bigDecimal.subtract(EasyConverter.of(subtrahend).toBigDecimalDefault(defaultNumber));
        return this;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 乘以一个数值
     *
     * @param  multiplicand value to be multiplied by this {@code Number}.
     * @return {@code Number}, not null
     */
    public EasyNumber multiply(final Object multiplicand) {
        return multiplyDefault(multiplicand, 1);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 乘以一个数值
     *
     * @param  multiplicand value to be multiplied by this {@code Number}.
     * @return {@code Number}, not null
     */
    public EasyNumber multiplyDefault(final Object multiplicand, final Object defaultNumber) {
        bigDecimal = bigDecimal.multiply(EasyConverter.of(multiplicand).toBigDecimalDefault(defaultNumber));
        return this;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 除以一个数值
     *
     * @param  divisor value by which this {@code Number} is to be divided.
     * @throws ArithmeticException if the exact quotient does not have a
     *         terminating decimal expansion
     * @return {@code Number}, not null
     */
    public EasyNumber divide(final Object divisor) {
        return divideDefault(divisor, 1);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 除以一个数值
     *
     * @param  divisor value by which this {@code Number} is to be divided.
     * @throws ArithmeticException if the exact quotient does not have a
     *         terminating decimal expansion
     * @return {@code Number}, not null
     */
    public EasyNumber divide(final Object divisor, final int scale) {
        return divideDefault(divisor, scale, RoundingMode.HALF_UP, 1);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 除以一个数值
     *
     * @param  divisor value by which this {@code Number} is to be divided.
     * @throws ArithmeticException if the exact quotient does not have a
     *         terminating decimal expansion
     * @return {@code Number}, not null
     */
    public EasyNumber divide(final Object divisor, final int scale, final RoundingMode roundingMode) {
        return divideDefault(divisor, scale, roundingMode, 1);
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 除以一个数值
     *
     * @param  divisor value by which this {@code Number} is to be divided.
     * @throws ArithmeticException if the exact quotient does not have a
     *         terminating decimal expansion
     * @return {@code Number}, not null
     */
    public EasyNumber divideDefault(final Object divisor, final Object defaultNumber) {
        bigDecimal = bigDecimal.divide(EasyConverter.of(divisor).toBigDecimalDefault(defaultNumber), RoundingMode.HALF_UP);
        return this;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 除以一个数值
     *
     * @param  divisor value by which this {@code Number} is to be divided.
     * @throws ArithmeticException if the exact quotient does not have a
     *         terminating decimal expansion
     * @return {@code Number}, not null
     */
    public EasyNumber divideDefault(final Object divisor, final int scale,
                                    final RoundingMode roundingMode, final Object defaultNumber) {
        bigDecimal = bigDecimal.divide(EasyConverter.of(divisor).toBigDecimalDefault(defaultNumber), scale,
                Optional.ofNullable(roundingMode).orElse(RoundingMode.HALF_UP));
        return this;
    }

    //-----------------------------------------------------------------------------------------------------------------
    /**
     ** 转换为Converter类
     *
     * @return {@code Converter}, not null
     */
    public EasyConverter toConverter(){
        return EasyConverter.of(bigDecimal);
    }

    //-----------------------------------------------------------------------------------------------------------------

}
